package erfgame.frontend.desktop.view.terrain.iso.handler;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import erfgame.core.Point3D;
import erfgame.core.entity.Entity;
import erfgame.core.graphics.renderer.chain.RendererChain;
import erfgame.core.world.terrain.insertion.SurfaceInsertion;

import erfgame.frontend.desktop.view.terrain.iso.EntitySelection;
import erfgame.frontend.desktop.view.terrain.iso.IsometricTerrainView;
import erfgame.frontend.desktop.view.terrain.iso.interaction.EntityInteractionDescriptionFactory;
import erfgame.frontend.desktop.view.terrain.iso.interaction.EntityInteractionDescriptionFactoryManager;
import erfgame.frontend.desktop.view.terrain.iso.interaction.EntityInteractionFactory;
import erfgame.frontend.desktop.view.terrain.iso.interaction.Interaction;
import erfgame.frontend.desktop.view.terrain.iso.interaction.InteractionDescription;

public class ContextMenuInteractionHandler extends BaseClickInteractionHandler {

	private EntitySelection selection;
	private IsometricTerrainView view;
	private EntityInteractionDescriptionFactoryManager factoryManager;
	
	public ContextMenuInteractionHandler( 
			IsometricTerrainView view, 
			EntitySelection selection,
			EntityInteractionDescriptionFactoryManager factoryManager ) {
		super( MouseEvent.BUTTON3 );
		this.view = view;
		this.selection = selection;
		this.factoryManager = factoryManager;
	}

	@Override
	protected boolean handleClick(MouseEvent e) {
		List<SurfaceInsertion> insertions = view.getInsertionsAt(e.getX(), e.getY());
		Entity toInteractWith = null;
		Point3D position = view.getTerrainPosition(e.getX(), e.getY(), new Point3D());
		Entity interacter = null;
		List<RendererChain> selected = selection.getSelected();
		for( int i=0; i<selected.size(); i++ ) {
			// TODO  merge options for multiple entities
			RendererChain chain = selected.get(i);
			Entity selectedEntity = chain.getHead().getEntity();
			if( selectedEntity != null ) {
				interacter = selectedEntity;
				break;
			}
		}
		for( int i=0; i<insertions.size(); i++ ) {
			SurfaceInsertion insertion = insertions.get( i );
			Entity selectedEntity = insertion.getRendererChain().getHead().getEntity();
			if( selectedEntity != null ) {
				toInteractWith = selectedEntity;
				break;
			}
		}
		EntityInteractionDescriptionFactory interactionDescriptionFactory;
		interactionDescriptionFactory = this.factoryManager.getFactory(interacter);
		if( interactionDescriptionFactory != null ) {
			List<InteractionDescription> descriptions = interactionDescriptionFactory.getInteractions(toInteractWith, position);
			showMenu( descriptions, toInteractWith, position, e.getX(), e.getY() );
			return true;
		} else {
			return false;
		}
	}
	
	private interface MenuHandler {
		void add( JMenuItem menuItem );
	}

	public void showMenu( 
			List<InteractionDescription> descriptions,
			Entity entity,
			Point3D position,
			int sx, int sy
	) {
		final JPopupMenu popupMenu = new JPopupMenu();
		createMenu( new MenuHandler() {
			public void add(JMenuItem menuItem) {
				popupMenu.add(menuItem);
			}
		}, descriptions, entity, position );
		popupMenu.show(this.view, sx, sy);
	}
	
	public void createMenu( 
			MenuHandler parent, 
			List<InteractionDescription> descriptions,
			final Entity entity, 
			final Point3D position
	) {
		for( int i=0; i<descriptions.size(); i++ ) {
			InteractionDescription description;
			description = descriptions.get(i);
			List<InteractionDescription> children;
			children = description.getChildren();
			JMenuItem menuItem;
			if( children != null && children.size() > 0 ) {
				final JMenu menu = new JMenu( description.getName() );
				createMenu(new MenuHandler() {
					public void add(JMenuItem menuItem) {
						menu.add(menuItem);
					}
				}, children, entity, position);
				menuItem = menu;
			} else {
				menuItem = new JMenuItem( description.getName() );
			}
			final EntityInteractionFactory interactionFactory;
			interactionFactory = description.getInteractionFactory();
			if( interactionFactory != null ) {
				menuItem.addActionListener( new ActionListener() {
					
					public void actionPerformed(ActionEvent e) {
						Interaction interaction = interactionFactory.createInteraction(entity, position);
						InteractionHandler handler = interaction.activate();
						if( handler != null ) {
							view.addInteractionHandler(handler);
						}
					}
				});
			}
			parent.add( menuItem );
		}
		
	}
}
